#ifndef __M_LOOP_H__
#define __M_LOOP_H__

#include "buffer.hpp"
#include <mutex>
#include <thread>
#include <condition_variable>

namespace log
{
    using Functor = std::function<void(Buffer &)>;
    enum class AsyncType
    {
        SAFE,
        UNSAFE
    };
    class AsyncLooper
    {
    public:
        using ptr = std::shared_ptr<AsyncLooper>;
        AsyncLooper(const Functor &cb, AsyncType type = AsyncType::SAFE)
            : _callback(cb), _type(type), _stop(false), _thread(std::thread(&AsyncLooper::threadEntry, this))
        {
        }
        ~AsyncLooper() { stop(); }
        void stop()
        {
            _stop = true;        //
            _c_con.notify_all(); // 唤醒所有工作进程
            _thread.join();      // 等待工作进程的退出
        }
        void push(const char *data, size_t len)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_type == AsyncType::SAFE)
                _p_con.wait(lock, [&]()
                            { return _productor.writeAbleSize() >= len; });
            _productor.push(data, len);
            _c_con.notify_one();
        }

    protected:
        // 用于交换缓冲区
        void threadEntry()
        {
            while (true)
            {
                // 加锁
                {
                    // 判断生产缓冲区有无数据，有则交换，无则阻塞
                    std::unique_lock<std::mutex> lock(_mutex);
                    // 防止数据还未被处理，线程就退出了
                    if (_stop && _productor.empty())
                        break;
                    // 线程退出前或生产者缓冲区有数据，就唤醒消费者进程
                    _c_con.wait(lock, [&]()
                                { return _stop || !_productor.empty(); });
                    _consumer.swap(_productor);
                    // 唤醒所有生产者进程
                    if (_type == AsyncType::SAFE)
                        _p_con.notify_all();
                }
                // 对消费缓冲区进行数据处理
                _callback(_consumer);
                // 初始化消费缓冲区
                _consumer.reset();
            }
        }

    private:
        AsyncType _type;     // 线程安全状态
        bool _stop;          // 工作器停止标志
        Buffer _consumer;    // 消费者缓冲区
        Buffer _productor;   // 生产者缓冲区
        std::thread _thread; // 异步工作器对应的工作线程
        std::mutex _mutex;
        std::condition_variable _c_con; // 消费者条件变量
        std::condition_variable _p_con; // 生产者条件变量
        Functor _callback;
    };
}
#endif